/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.query;

import edu.pdx.cs.guavadata.Channel;
import edu.pdx.cs.guavadata.Transform;
import edu.pdx.cs.guavadata.domain.Domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 *
 * @author VuTran
 */
public class Project extends Operator {

    // Relational algebra project operator, list of column aliases to project
    // Columns (and domains) will be in the order of the columns to project in the output

    Operator child;

    public Operator getChild() {
        return child;
    }

    public void setChild(Operator child) {
        this.child = child;
    }

    public Project(Operator child, Collection<String> columnsToProject) {
        this.child = child;
        child.parent = this;
        List<String> toProject = new ArrayList<String>(columnsToProject);

        // Assemble the columns for output, and perform basic query checking
        this.exposedColumns = new ArrayList<String>();
        this.exposedDomains = new ArrayList<Domain>();
        for (int i = 0; i < child.exposedColumns.size(); i++) {
            if (toProject.contains(child.exposedColumns.get(i))) {
                this.exposedColumns.add(child.exposedColumns.get(i));
                this.exposedDomains.add(child.exposedDomains.get(i));
            }
        }

        // Dummy check - same number of columns as expected
        try {
            if (this.exposedColumns.size() != toProject.size())
                throw new Exception("Not all columns in the project list appear in the base query.");
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    @Override
    public SqlText visit(Provider qv) {
        return qv.transform(this);
    }

    @Override
    public void visit(Channel c, String table) {
        c.mapAliases(this, table);
    }

    @Override
    public void visit(Transform t, Command c) {
        t.expand(this, c);
    }

    @Override
    public void notifyChange(Operator old, Operator newOp) {
        if (this.child == old) {
            this.child = newOp;
            newOp.parent = this;
        }
    }

    @Override
    public Operator clone() {
        return new Project(child.clone(), exposedColumns);
    }
}
